const httpProxy = require('http-proxy-middleware');
const koa2Connect = require('koa2-connect');

module.exports = (app, proxyConfig) => {
  proxy(app, proxyConfig);
};

function proxy(app, proxyConfig) {
  // 处理代理配置
  if (!Array.isArray(proxyConfig)) {
    proxyConfig = Object.keys(proxyConfig).map((context) => {
      let proxyOptions;

      // For backwards compatibility reasons.
      const correctedContext = context.replace(/^\*$/, '**').replace(/\/\*$/, '');
      if (typeof proxyConfig[context] === 'string') {
        proxyOptions = {
          context: correctedContext,
          target: proxyConfig[context]
        };
      } else {
        proxyOptions = Object.assign({}, proxyConfig[context]);
        proxyOptions.context = correctedContext;
      }
      proxyOptions.logLevel = proxyOptions.logLevel || 'warn';

      return proxyOptions;
    });
  }
  const getHttpProxy = (proxyConfig) => {
    const context = proxyConfig.context || proxyConfig.path;
    if (proxyConfig.target) {
      return koa2Connect(httpProxy(context, proxyConfig));
    }
  };

  /**
   * 假设指定的代理配置为:
   * proxy: [
   *   {
   *     context: ...,
   *     ...options...
   *   },
   *   // or:
   *   function() {
   *     return {
   *       context: ...,
   *       ...options...
   *     };
   *   }
   * ]
   */
  proxyConfig.forEach((proxyConfigOrCallback) => {
    let proxyConfig;
    let proxyMiddleware;
    if (typeof proxyConfigOrCallback === 'function') {
      proxyConfig = proxyConfigOrCallback();
    } else {
      proxyConfig = proxyConfigOrCallback;
    }

    proxyMiddleware = getHttpProxy(proxyConfig);

    app.use((ctx, next) => {
      if (typeof proxyConfigOrCallback === 'function') {
        const newProxyConfig = proxyConfigOrCallback();
        if (newProxyConfig !== proxyConfig) {
          proxyConfig = newProxyConfig;
          proxyMiddleware = getHttpProxy(proxyConfig);
        }
      }
      const bypass = typeof proxyConfig.bypass === 'function';
      // eslint-disable-next-line
      const bypassUrl = bypass && proxyConfig.bypass(ctx, proxyConfig) || false;

      if (bypassUrl) {
        ctx.url = bypassUrl;
        next();
      } else if (proxyMiddleware) {
        return proxyMiddleware(ctx, next);
      } else {
        next();
      }
    });
  });
}
